home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 21
/
Cream of the Crop 21 (Terry Blount) (October 1996).iso
/
os2
/
freetype.zip
/
ttcalc.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1996-09-07
|
14KB
|
552 lines
{****************************************************************************}
{* *}
{* TTCalc *}
{* *}
{* This units holds most of the arithmetic and vectorial operations *}
{* used by the FreeType engine. *}
{* *}
{****************************************************************************}
unit TTCalc;
interface
uses TTTypes, TTError, TTVars;
procedure Do16( var S );
procedure Do16s( var S; Cnt : Int );
procedure Do32( var L );
procedure Do32s( var L; Cnt : int );
function MulDiv( A, B, C : Int32 ): Int32;
procedure Add64( var X, Y, Z : Int64 );
procedure Sub64( var X, Y, Z : Int64 );
procedure MulTo64( X, Y : Int32; var Z : Int64 );
function Div64by32( var X : Int64; Y : Int32 ) : Int32;
function Order64( var Z : Int64 ) : int;
function Order32( Z : Int32 ) : int;
function Sqrt32( L : LongInt ): LongInt;
function Sqrt64( L : Int64 ): LongInt;
function MulVec( var L : Int64; (* This is 48 bits number *)
F : TUnitVector; (* Freedom vector *)
P : TUnitVector; (* Projection vector *)
var R : TVector (* Result Vector *)
)
: boolean;
function Norm( X, Y : F26dot6 ): F26dot6;
function UnitNorm( V : TUnitVector ): F2dot14;
function Dot( U, V : TVector ): F26dot6;
function Project( V : TVector; U : TUnitVector ): F26dot6;
function MoveVec1 ( var V : TVector; H : F26dot6 ) : boolean;
function MoveVec2 ( var V : TVector; H : F26dot6;
var V2 : TVector )
: boolean;
function AlignVecs( var A, B : TVector
)
: boolean;
function Barycentre( var A1, B1, I1, A2, B2 : TVector;
var I2 : TVector
)
: boolean;
function Interpolate( A1, B1, I1,
A2, B2 : F26dot6;
var I2 : F26dot6
)
: boolean;
function Normalize( U, V : F26dot6; var R : TUnitVector ): boolean;
function Intersect( var A, B, C, D : TVector;
var R : TVector
)
: boolean;
implementation
(* Load the appropriate implementation of processor and
bitness dependent routines *)
{$IFDEF OS2}
{$I TTCALC32.INC}
{$ELSE}
{$I TTCALC16.INC}
{$ENDIF}
const
Roots : array[0..62] of LongInt
= (
1, 1, 2, 3, 4, 5, 8, 11,
16, 22, 32, 45, 64, 90, 128, 181,
256, 362, 512, 724, 1024, 1448, 2048, 2896,
4096, 5892, 8192, 11585, 16384, 23170, 32768, 46340,
65536, 92681, 131072, 185363, 262144, 370727,
524288, 741455, 1048576, 1482910, 2097152, 2965820,
4194304, 5931641, 8388608, 11863283, 16777216, 23726566,
33554432, 47453132, 67108864, 94906265,
134217728, 189812531, 268435456, 379625062,
536870912, 759250125, 1073741824, 1518500250,
2147483647
);
(**************************************************)
(* Integer Square Root *)
function Sqrt32( L : LongInt ): LongInt;
var
R, S : LongInt;
begin
if L<=0 then Sqrt32:=0 else
if L=1 then Sqrt32:=1 else
begin
R:=Roots[ Order32(L) ];
Repeat
S:=R;
R:=( R+ L div R ) shr 1;
until ( R<=S ) and ( R*R<=L );
Sqrt32:=R;
end;
end;
(**************************************************)
(* Integer Square Root *)
function Sqrt64( L : Int64 ): LongInt;
var
L2 : Int64;
R, S : LongInt;
begin
if L.Hi<0 then Sqrt64:=0 else
begin
S := Order64(L);
if S=0 then Sqrt64:=1 else
begin
R:=Roots[S];
Repeat
S:=R;
R:=( R+Div64by32(L,R) ) shr 1;
MulTo64 ( R, R, L2 );
Sub64 ( L, L2, L2 );
until ( R<=S ) and ( L2.Hi>=0 );
Sqrt64:=R;
end
end
end;
(*******************************************************)
(* Special routine used to compute point displacements *)
(* *)
(* This routine could be optimized to inline assembly *)
(* for those of you concerned with speed *)
function MulVec( var L : Int64; (* This is 48 bits number *)
F : TUnitVector; (* Freedom vector *)
P : TUnitVector; (* Projection vector *)
var R : TVector (* Result Vector *)
)
: boolean;
var
A, B : Int32;
T, T2: Int64;
begin
B := Int32(F.x)*P.x + Int32(F.y)*P.y;
if B=0 then
begin
MulVec:=False; (* B := Fx.Px + Fy.Py *)
R.x:=0;
R.y:=0;
exit;
end;
MulTo64( L.Lo, F.x, T );
MulTo64( L.Hi, F.x, T2 );
Inc( T.Hi, T2.Lo );
R.x := Div64by32( T, B ); (* Rx := L*Fx/B *)
MulTo64( L.Lo, F.y, T );
MulTo64( L.Hi, F.y, T2 );
Inc( T.Hi, T2.Lo );
R.y := Div64by32( T, B ); (* Ry := L*Fy/B *)
MulVec:=True;
end;
(**************************************************)
(* Vector length *)
function Norm( X, Y : F26dot6 ): F26dot6;
var
T1, T2 : Int64;
begin
MulTo64( X, X, T1 );
MulTo64( Y, Y, T2 );
Add64( T1, T2, T1 );
Norm := Sqrt64( T1 );
end;
(**************************************************)
(* Unit vector Length *)
function UnitNorm( V : TUnitVector ): F2dot14;
begin
UnitNorm := Sqrt32( Int32(V.x)*V.x + Int32(V.y)*V.y );
end;
(**************************************************)
(* Scalar vector product *)
function Dot( U, V : TVector ): F26dot6;
var
T1, T2 : Int64;
begin
MulTo64( U.x, V.x, T1 );
MulTo64( U.y, V.y, T2 );
Add64( T1, T2, T1 );
Dot := Div64by32( T1, 64 );
end;
(**************************************************)
(* Projection *)
function Project( V : TVector; U : TUnitVector ): F26dot6;
var
T1, T2 : Int64;
begin
MulTo64( V.x, U.x, T1 );
MulTo64( V.x, U.x, T2 );
Add64( T1, T2, T1 );
Project := Div64by32( T1, $4000 );
end;
(**************************************************)
(* *)
(* MoveVec1 : Move a point according to *)
(* PV and FV *)
(* FALSE if PV.FV = 0 *)
(**************************************************)
function MoveVec1( var V : TVector; H : F26dot6 ) : boolean;
var
T : Int64;
R : TVector;
begin
with GS do
with V do
begin
MulTo64( H, $4000, T );
if MulVec( T, freeVector,
projVector,
R )
then
begin
inc( X, R.x );
inc( Y, R.y );
MoveVec1:=True;
end
else
begin
MoveVec1:=False;
Error:=TT_ErrMsg_Divide_By_Zero;
end
end
end;
(**************************************************)
(* *)
(* MoveVec2 : Déplace un point en fonction des *)
(* PV et FV *)
(* FALSE si PV.FV = 0 *)
(**************************************************)
function MoveVec2 ( var V : TVector; H : F26dot6;
var V2 : TVector )
: boolean;
var
R : TVector;
T1,
T2 : Int64;
begin
with GS do
with V do